package site.hanzhe.example.coord.utils;

import cn.hutool.core.util.NumberUtil;
import org.joml.Matrix3d;
import org.joml.Vector3d;
import site.hanzhe.example.coord.entity.Point2D;
import site.hanzhe.example.coord.entity.Point3D;

import java.util.List;
import java.util.stream.Collectors;

/**
 * PointUtil
 *
 * @author 张涵哲
 * @since 2023-06-24 21:32
 */

public class PointUtil {

    /**
     * 将三维坐标点转换为二维坐标点（正交投影 x=x, y=z）
     * @author 张涵哲
     * @since 2023-05-26 18:26
     */
    public static Point2D toPoint2D(Point3D point3D) {
        return new Point2D(point3D.getX(), point3D.getZ());
    }

    /**
     * 将三维坐标组转换为二维坐标组（正交投影 x=x, y=z）
     * @author 张涵哲
     * @since 2023-05-26 18:27
     */
    public static List<Point2D> toPointList2D(List<Point3D> points) {
        return points.stream().map(PointUtil::toPoint2D).collect(Collectors.toList());
    }

    /**
     * 按X轴旋转三维坐标组
     * @author 张涵哲
     * @since 2023-05-26 10:40
     * @param points 三维坐标组
     * @param angleX X轴旋转角度
     * @param angleY Y轴旋转角度
     * @param angleZ Z轴旋转角度
     */
    public static List<Point3D> rotate(List<Point3D> points, double angleX, double angleY, double angleZ) {
        // 构建旋转矩阵
        Matrix3d matrix = new Matrix3d()
                .rotateX(Math.toRadians(angleX))
                .rotateY(Math.toRadians(angleY))
                .rotateZ(Math.toRadians(angleZ));
        // 构建3d坐标点，用于存储转换后的坐标信息
        Vector3d dist = new Vector3d();
        // stream遍历坐标组，将坐标进行旋转后返回新坐标
        return points.stream().map(point -> {
            matrix.transform(point.getX(), point.getY(), point.getZ(), dist);
            return new Point3D(dist.x, dist.y, dist.z);
        }).collect(Collectors.toList());
    }

    /**
     * 将2D坐标组进行四舍五入
     * @author 张涵哲
     * @since 2023-05-29 9:32
     * @param points  2D坐标组
     * @param decimal 小数位数
     */
    public static List<Point2D> round(List<Point2D> points, int decimal) {
        return points.stream().map(item -> {
            double x = NumberUtil.round(item.getX(), decimal).doubleValue();
            double y = NumberUtil.round(item.getY(), decimal).doubleValue();
            return new Point2D(x, y);
        }).collect(Collectors.toList());
    }

}
